﻿/********
* 
* 
*  Description:
*  Create By Kain at 4/2/2011 2:31:42 PM
*  
*
*  Revision History:
*  Date                  Who                 What
*  
* 
*/

#region

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.IO;
using System.Collections.Specialized;
using System.Reflection;
using System.Runtime.Serialization;

#endregion

namespace Cherry.Agile.ServiceModel.Runtime
{
    [Serializable]
    public class ServicePackage
    {
        private string name;
        private string fullName;

        private ListDictionary settings = new ListDictionary();

        private string basePath;
        private string configFile;
        private string binPath;
        private bool autoBinPath;

        private string assembly;
        
        public ServicePackage() { }

        /// <summary>
        /// Construct a package, specifying the name of the package.
        /// If the package name is an assembly file type (dll or exe)
        /// then the resulting package represents a single assembly.
        /// Otherwise it is a container for multiple assemblies.
        /// </summary>
        /// <param name="serviceFile">The name of the package</param>
        public ServicePackage(string serviceFile,string baseAddress = null)
        {
            this.fullName = serviceFile;
            this.name = Path.GetFileName(serviceFile);
            if (IsAssemblyFileType(serviceFile))
            {
                if (!Path.IsPathRooted(serviceFile))
                    throw new ArgumentException("Assembly in ServicePackage must be specified as an absolute path", "name");
                //assembly = System.Reflection.Assembly.LoadFile(serviceFile);
                assembly = serviceFile;
            }
            BaseAddress = baseAddress;
        }
        [IgnoreDataMember]
        public int Id { get { return fullName.GetHashCode(); } }

        [IgnoreDataMember]
        public string BaseAddress { get; set; }

        /// <summary>
        /// Gets the name of the package
        /// </summary>
        [IgnoreDataMember]
        public string Name
        {
            get { return name; }
        }

        /// <summary>
        /// Gets the full name of the package, which is usually
        /// the path to the NUnit project used to create the it
        /// </summary>
        [DataMember]
        public string FullName
        {
            get { return fullName; }
        }

        /// <summary>
        /// The BasePath to be used in loading the assemblies
        /// </summary>
        [IgnoreDataMember]
        public string BasePath
        {
            get { return basePath; }
            set { basePath = value; }
        }

        /// <summary>
        /// The configuration file to be used
        /// </summary>
        [IgnoreDataMember]
        public string ConfigurationFile
        {
            get { return configFile; }
            set { configFile = value; }
        }

        /// <summary>
        /// Addditional directories to be probed when loading assemblies
        /// </summary>
        [IgnoreDataMember]
        public string PrivateBinPath
        {
            get { return binPath; }
            set { binPath = value; }
        }

        /// <summary>
        /// Indicates whether the probing path should be generated
        /// automatically based on the list of assemblies.
        /// </summary>
        [IgnoreDataMember]
        public bool AutoBinPath
        {
            get { return autoBinPath; }
            set { autoBinPath = value; }
        }

        /// <summary>
        /// Assemblies to be loaded. At least one must be specified.
        /// </summary>
        [IgnoreDataMember] public string AssemblyFile
        {
            get { return assembly; }
        }

        /// <summary>
        /// Gets the dictionary of settings for this ServicePackage
        /// </summary>
        [IgnoreDataMember]
        public IDictionary Settings
        {
            get { return settings; }
        }

        /// <summary>
        /// Return the value of a setting or a default.
        /// </summary>
        /// <param name="name">The name of the setting</param>
        /// <param name="defaultSetting">The default value</param>
        /// <returns></returns>
        public object GetSetting(string name, object defaultSetting)
        {
            object setting = settings[name];

            return setting == null ? defaultSetting : setting;
        }

        /// <summary>
        /// Return the value of a string setting or a default.
        /// </summary>
        /// <param name="name">The name of the setting</param>
        /// <param name="defaultSetting">The default value</param>
        /// <returns></returns>
        public string GetSetting(string name, string defaultSetting)
        {
            object setting = settings[name];

            return setting == null ? defaultSetting : (string)setting;
        }

        /// <summary>
        /// Return the value of a bool setting or a default.
        /// </summary>
        /// <param name="name">The name of the setting</param>
        /// <param name="defaultSetting">The default value</param>
        /// <returns></returns>
        public bool GetSetting(string name, bool defaultSetting)
        {
            object setting = settings[name];

            return setting == null ? defaultSetting : (bool)setting;
        }

        /// <summary>
        /// Return the value of an int setting or a default.
        /// </summary>
        /// <param name="name">The name of the setting</param>
        /// <param name="defaultSetting">The default value</param>
        /// <returns></returns>
        public int GetSetting(string name, int defaultSetting)
        {
            object setting = settings[name];

            return setting == null ? defaultSetting : (int)setting;
        }

        /// <summary>
        /// Return the value of a enum setting or a default.
        /// </summary>
        /// <param name="name">The name of the setting</param>
        /// <param name="defaultSetting">The default value</param>
        /// <returns></returns>
        public System.Enum GetSetting(string name, System.Enum defaultSetting)
        {
            object setting = settings[name];

            return setting == null ? defaultSetting : (System.Enum)setting;
        }

        private static bool IsAssemblyFileType(string path)
        {
            string extension = Path.GetExtension(path).ToLower();
            return extension == ".dll" || extension == ".exe";
        }
    }
}
